﻿/*********************************************************

    Copyright (c) Microsoft. All rights reserved.
    This code is licensed under the Microsoft Public License.
    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.

*********************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using OData.Silverlight;

namespace SL_OData_Explorer
{
    public partial class ODataQueryBuilder : ChildWindow
    {
        EntityType entityType;
        public ODataQueryBuilder(EntityType entityType, string currentURI) :
            this()
        {
            this.entityType = entityType;
            currentURI = RemovePreExistingFilter(currentURI);

            HasQueryOptions = currentURI.Contains('?');

            txtCurrentUri.Text = currentURI;


            BindEntityTypeFilters();
        }

        private string RemovePreExistingFilter(string currentURI)
        {
            Uri candidateUri = new Uri(currentURI, UriKind.RelativeOrAbsolute);
            if (!candidateUri.IsAbsoluteUri)
            {
                candidateUri = new Uri(String.Format("{0}/{1}", App.MDViewModel.CurrentModel.ServiceDocument.BaseUri.OriginalString.TrimEnd('/'), currentURI.TrimStart('/')), UriKind.Absolute);
            }

            if (!String.IsNullOrEmpty(candidateUri.Query) && candidateUri.Query.Length > 0)
            {
                List<string> queryStringComponents = candidateUri.Query.Split('&').ToList();
                var filterComponents = queryStringComponents.Where(str => str.Contains("$filter")).ToList();

                foreach (string filterCOmponent in filterComponents)
                {
                    queryStringComponents.Remove(filterCOmponent);
                }

                currentURI = currentURI.Split('?')[0];
                currentURI = String.Format("{0}?{1}", currentURI, String.Join("&", queryStringComponents.ToArray()));
                currentURI = currentURI.Replace("?&", "?");
                currentURI = currentURI.TrimEnd('?');
            }
            return currentURI;
        }
        private void BindEntityTypeFilters()
        {
            cbEntityProperties.DisplayMemberPath = "PropertyName";
            cbEntityProperties.ItemsSource = entityType.Properties.Where(property => property.PropertyType == typeof(string) || property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(int));
        }

        public ODataQueryBuilder()
        {
            InitializeComponent();
            btnAddQueryOption.Click += new RoutedEventHandler(btnAddQueryOption_Click);
            cbEntityProperties.SelectionChanged += new SelectionChangedEventHandler(cbEntityProperties_SelectionChanged);
        }
        bool HasQueryOptions = false;

        private string GetQueryFragment()
        {
            EntityProperty propertySelected = cbEntityProperties.SelectedItem as EntityProperty;
            string propertyName = propertySelected.PropertyName;
            string propertyValue = txtValue.Text;
            if (propertySelected.PropertyType == typeof(DateTime))
            {
                propertyValue = txtDateTimeValue.Text;
            }
            QueryFilterOperation filterOperation = cbOperators.SelectedItem as QueryFilterOperation;
            string queryFragment = filterOperation.Encode(propertyName, propertyValue);
            return queryFragment;
        }
        bool isFirstCondition = true;
        void btnAddQueryOption_Click(object sender, RoutedEventArgs e)
        {
            if (!txtCurrentUri.Text.Contains("$filter"))
            {
                string filterText = HasQueryOptions ? "&" : "?";
                txtCurrentUri.Text = txtCurrentUri.Text + filterText + "$filter=";
            }
            if (!isFirstCondition)
            {
                txtCurrentUri.Text += " and ";
            }
            isFirstCondition = false;
            txtCurrentUri.Text += GetQueryFragment();

            StackPanel spQueryOption = new StackPanel() { Orientation = Orientation.Horizontal };
            spQueryOption.Children.Add(
                new TextBlock()
                {
                    Text = ((EntityProperty)cbEntityProperties.SelectedItem).PropertyName,
                    Margin = new Thickness(5)
                }
                );

            spQueryOption.Children.Add(
                new TextBlock()
                {
                    Text = ((QueryFilterOperation)cbOperators.SelectedItem).Display,
                    Margin = new Thickness(5)
                }
                );

            spQueryOption.Children.Add(
                new TextBlock()
                {
                    Text = txtValue.Text,
                    Margin = new Thickness(5)
                }
                );

            spQueryOptions.Children.Add(spQueryOption);
            HasQueryOptions = true;

            txtValue.Visibility = System.Windows.Visibility.Visible;
            txtDateTimeValue.Visibility = System.Windows.Visibility.Collapsed;
        }

        void cbEntityProperties_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            EntityProperty property = cbEntityProperties.SelectedItem as EntityProperty;
            if (property != null)
            {
                cbOperators.DisplayMemberPath = "Display";
                if (property.PropertyType == typeof(string))
                {
                    cbOperators.ItemsSource = QueryFilterOperation.StringFilters;
                }
                else if (property.PropertyType == typeof(int))
                {
                    cbOperators.ItemsSource = QueryFilterOperation.IntFilters;
                }
                else if (property.PropertyType == typeof(DateTime))
                {
                    cbOperators.ItemsSource = QueryFilterOperation.DateFilters;
                    txtDateTimeValue.Visibility = System.Windows.Visibility.Visible;
                    txtValue.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
        }

        private void OnEnter(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                btnAddQueryOption_Click(sender, e);
            }
        }
    }
}

